'use strict';

/**查找字符串
 * @param SourceString : string 需要搜索的字符串数据源
 * @param findKeyword : string 需要查找的关键字
 * @param onlyStrict : boolean 使用严格模式
 * @returns string|undefined
 * */
function findString(SourceString, findKeyword, onlyStrict) {
    if (typeof onlyStrict !== "boolean") {
        onlyStrict = false;
    }
    let finalString = undefined;
    let toLower1 = SourceString.toLowerCase(); //源字符串转小写
    let toLower2 = findKeyword.toLowerCase(); //查找关键字转小写
    let ExtRc = "";
    if (onlyStrict === true) {
        for (let icc = 0; icc < SourceString.length; icc++) {
            ExtRc = toLower1.substr(icc, findKeyword.length);
            if (ExtRc === findKeyword) {
                finalString = SourceString.substr(icc, findKeyword.length);
                break;
            }
        }
    } else {
        for (let occ = 0; occ < toLower1.length; occ++) {
            ExtRc = toLower1.substr(occ, toLower2.length);
            if (ExtRc === toLower2) {
                finalString = SourceString.substr(occ, findKeyword.length);
                break;
            }
        }
    }
    return finalString;
}

/**查找字符串Ex版
 * ```
 *@param {{
 * SourceStringData:string,
 * FindKeyWord:string,
 * EnableStrictMode:boolean,
 * FindDirection:number,
 * RetValueType:number
 * }} BasisParameterObject 形参对象
 *
 * SourceStringData：要搜索的数据源、数据类型（字符串）
 * ```
 * FindKeyWord：搜索关键字、数据类型（字符串）
 * ```
 * EnableStrictMode：是否使用严格模式（区分大小写）、布尔值、默认为false
 * ```
 * FindDirection：搜索方向、数据类型（整数型）0:从数据源的左边开始搜索、1:从数据源的右边开始搜索
 * ```
 * RetValueType：搜索结果返回类型、数据类型（整数型）0：返回搜索到的匹配数据、1：返回搜索到的匹配数据的起始位置、2：将前两者的内容结合成数组返回
 * ```
 * @returns string|number|Array
 */
function findStringEx(BasisParameterObject) {
    let finalReturnValue;
    let SourceStringData;
    let FindKeyWord;
    let EnableStrictMode = false;
    let FindDirection = 0;
    let RetValueType = 0;

    function notEmptyDetect(data) {
        let detectValue = undefined;
        if (Object.prototype.toString.call(data) === "[object Array]") {
            if (data.length > 0) {
                detectValue = true;
            } else {
                detectValue = false;
            }
        } else if (Object.prototype.toString.call(data) === "[object Object]") {
            let count = 0;
            for (let num in data) {
                count++;
                break;
            }
            if (count > 0) {
                detectValue = true;
            } else {
                detectValue = false;
            }
        }
        return detectValue;
    }

    if (Object.prototype.toString.call(BasisParameterObject) === "[object Object]") {
        switch (notEmptyDetect(BasisParameterObject)) {
            case true:
                let EffectiveQuantity = 0;
                for (let detectAttr in BasisParameterObject) {
                    switch (detectAttr.toLowerCase()) {
                        case "sourcestringdata":
                            if (typeof BasisParameterObject[detectAttr] === "string") {
                                SourceStringData = BasisParameterObject[detectAttr];
                            } else {
                                throw new Error("SourceStringData属性包含的数据不是字符串！");
                            }
                            EffectiveQuantity++;
                            break;
                        case "findkeyword":
                            if (typeof BasisParameterObject[detectAttr] === "string") {
                                FindKeyWord = BasisParameterObject[detectAttr];
                            } else {
                                throw new Error("FindKeyWord属性包含的数据不是字符串！");
                            }
                            EffectiveQuantity++;
                            break;
                        case "enablestrictmode":
                            if (typeof BasisParameterObject[detectAttr] === "boolean") {
                                EnableStrictMode = BasisParameterObject[detectAttr];
                            } else {
                                throw new Error("EnableStrictMode属性包含的数据不是布尔值！");
                            }
                            break;
                        case "finddirection":
                            if (typeof BasisParameterObject[detectAttr] === "number") {
                                switch (BasisParameterObject[detectAttr]) {
                                    case 0:
                                        FindDirection = BasisParameterObject[detectAttr];
                                        break;
                                    case 1:
                                        FindDirection = BasisParameterObject[detectAttr];
                                        break;
                                    default:
                                        throw new Error("FindDirection属性的属性值异常，仅能为0或者为1（0：从左边查找，1：从右边查找）、默认值为0");
                                }
                            } else {
                                throw new Error("FindDirection属性包含的数据不是纯数字！");
                            }
                            break;
                        case "retvaluetype":
                            if (typeof BasisParameterObject[detectAttr] === "number") {
                                switch (BasisParameterObject[detectAttr]) {
                                    case 0:
                                        RetValueType = BasisParameterObject[detectAttr];
                                        break;
                                    case 1:
                                        RetValueType = BasisParameterObject[detectAttr];
                                        break;
                                    case 2:
                                        RetValueType = BasisParameterObject[detectAttr];
                                        break;
                                    default:
                                        throw new Error("RetValueType属性的属性值异常，仅能为0或者为1或者为2（0：返回匹配查找到的字符串，1：返回匹配查找到的字符串从左到右的起始位置，2：将前两者的数据组合成数组并返回。默认值为0）");
                                }
                            } else {
                                throw new Error("RetValueType属性包含的数据不是纯数字！");
                            }
                            break;
                    }
                }
                if (EffectiveQuantity < 2) {
                    throw new Error("有效参数不足于3个！");
                }
                if (SourceStringData.length <= FindKeyWord.length) {
                    throw new Error("要查找的关键字比源字符串数据内容还要多，无法实现查找！");
                }
                if (EnableStrictMode) {
                    let esmCount = 0;
                    switch (FindDirection) {
                        case 0:
                            for (; esmCount < SourceStringData.length; esmCount++) {
                                if (FindKeyWord === SourceStringData.substr(esmCount, FindKeyWord.length)) {
                                    switch (RetValueType) {
                                        case 0:
                                            finalReturnValue = SourceStringData.substr(esmCount, FindKeyWord.length);
                                            break;
                                        case 1:
                                            finalReturnValue = esmCount;
                                            break;
                                        case 2:
                                            finalReturnValue = [SourceStringData.substr(esmCount, FindKeyWord.length), esmCount];
                                            break;
                                    }
                                    break;
                                }
                            }
                            break;
                        case 1:
                            esmCount = SourceStringData.length;
                            for (; esmCount >= 0; esmCount--) {
                                if (FindKeyWord === SourceStringData.substr(esmCount, FindKeyWord.length)) {
                                    switch (RetValueType) {
                                        case 0:
                                            finalReturnValue = SourceStringData.substr(esmCount, FindKeyWord.length);
                                            break;
                                        case 1:
                                            finalReturnValue = esmCount;
                                            break;
                                        case 2:
                                            finalReturnValue = [SourceStringData.substr(esmCount, FindKeyWord.length), esmCount];
                                            break;
                                    }
                                    break;
                                }
                            }
                            break;
                    }
                } else {
                    let NoESM = 0;
                    switch (FindDirection) {
                        case 0:
                            for (; NoESM < SourceStringData.length; NoESM++) {
                                if (FindKeyWord === SourceStringData.substr(NoESM, FindKeyWord.length)) {
                                    switch (RetValueType) {
                                        case 0:
                                            finalReturnValue = SourceStringData.substr(NoESM, FindKeyWord.length);
                                            break;
                                        case 1:
                                            finalReturnValue = NoESM;
                                            break;
                                        case 2:
                                            finalReturnValue = [SourceStringData.substr(NoESM, FindKeyWord.length), NoESM];
                                            break;
                                    }
                                    break;
                                }
                            }
                            break;
                        case 1:
                            NoESM = SourceStringData.length;
                            for (; NoESM >= 0; NoESM--) {
                                if (FindKeyWord === SourceStringData.substr(NoESM, FindKeyWord.length)) {
                                    switch (RetValueType) {
                                        case 0:
                                            finalReturnValue = SourceStringData.substr(NoESM, FindKeyWord.length);
                                            break;
                                        case 1:
                                            finalReturnValue = NoESM;
                                            break;
                                        case 2:
                                            finalReturnValue = [SourceStringData.substr(NoESM, FindKeyWord.length), NoESM];
                                            break;
                                    }
                                    break;
                                }
                            }
                            break;
                    }
                }
                break;
            case false:
                throw new Error("形参“BasisParameterObject”收到了不包含任何数据的空对象！");
            default:
                throw new Error("形参“BasisParameterObject”收到了无效数据！");
        }
    } else {
        throw new Error("形参“BasisParameterObject”仅能为对象！");
    }
    return finalReturnValue;
}

/**查找存在多个类同等字符串
 * ```
 * @param SourcesString : string 要搜索的字符数据源
 * @param NeedSearchString : string  要搜索的关键字
 * @param EnableStrict : boolean 是否使用严格模式(True Or False)
 * @param SearchDirection : number 搜索方向(0:从左边搜索，1:从右边搜索)
 * @param ReturnValueType : number 返回搜索的结果(0:返回要搜索的字符串在字符源存在数量,1:返回搜索到与其匹配的字符内容数组)
 *
 *@example let searchResult= findMultiEqualString("dcdcdGBc","dgbc",false,1)
 */
function findMultiEqualString(SourcesString, NeedSearchString, EnableStrict, ReturnValueType, SearchDirection) {
    let FinalReturnValue;
    if (typeof EnableStrict !== "boolean") {
        EnableStrict = false;
    }
    if (typeof ReturnValueType !== "number") {
        ReturnValueType = 0;
    }
    if (typeof SearchDirection !== "number") {
        SearchDirection = 0;
    }
    let convertSourcesString;
    let convertNeedSearchString;
    switch (typeof SourcesString) {
        case "string":
            convertSourcesString = SourcesString;
            break;
        case "number":
            if (isNaN(SourcesString)) {
                throw new Error("NaN值不能作为源字符串！");
            } else {
                convertSourcesString = SourcesString + "";
            }
            break;
        default:
            throw new Error("SourcesString形参仅能是字符串或数字！");
    }
    switch (typeof NeedSearchString) {
        case "string":
            convertNeedSearchString = NeedSearchString;
            break;
        case "number":
            if (isNaN(NeedSearchString)) {
                throw new Error("无法查找NaN值！");
            } else {
                convertNeedSearchString = NeedSearchString + "";
            }
            break;
        default:
            throw new Error("NeedSearchString形参仅能是字符串或数字！");
    }
    let SearchStringLength = convertNeedSearchString.length;
    let SourcesConvertLowerCase = convertSourcesString.toLowerCase();
    let SearchStringConvertLowerCase = convertNeedSearchString.toLowerCase();

    function strict1() {
        if (EnableStrict) {
            if (convertNeedSearchString === convertSourcesString.substr(currentPosition, SearchStringLength)) {
                FinalReturnValue[FinalReturnValue.length] = convertSourcesString.substr(currentPosition, SearchStringLength);
            }
        } else {
            if (SearchStringConvertLowerCase === SourcesConvertLowerCase.substr(currentPosition, SearchStringLength)) {
                FinalReturnValue[FinalReturnValue.length] = SourcesConvertLowerCase.substr(currentPosition, SearchStringLength);
            }
        }
    }

    if (SearchStringLength > convertSourcesString.length) {
        console.error("要搜索的字符串的长度大于源字符串的长度，无法搜索！");
    } else {
        let currentPosition = 0;
        switch (ReturnValueType) {
            case 0:
                FinalReturnValue = 0;
                if (SearchDirection === 0) {
                    for (; currentPosition < convertSourcesString.length; currentPosition++) {
                        if (currentPosition > convertSourcesString.length) {
                            break;
                        }
                        if (EnableStrict) {
                            if (convertNeedSearchString === convertSourcesString.substr(currentPosition, SearchStringLength)) {
                                FinalReturnValue++;
                            }
                        } else {
                            if (SearchStringConvertLowerCase === SourcesConvertLowerCase.substr(currentPosition, SearchStringLength)) {
                                FinalReturnValue++;
                            }
                        }
                    }
                } else {
                    currentPosition = convertSourcesString.length - SearchStringLength;
                    for (; currentPosition > 0; currentPosition--) {
                        if (currentPosition < SearchStringLength) {
                            break;
                        } else if (currentPosition === SearchStringLength) {
                            if (EnableStrict) {
                                if (convertNeedSearchString === convertSourcesString.substr(0, SearchStringLength)) {
                                    FinalReturnValue++;
                                }
                            } else {
                                if (SearchStringConvertLowerCase === SourcesConvertLowerCase.substr(0, SearchStringLength)) {
                                    FinalReturnValue++;
                                }
                            }
                            break;
                        } else {
                            if (EnableStrict) {
                                if (convertNeedSearchString === convertSourcesString.substr(currentPosition, SearchStringLength)) {
                                    FinalReturnValue++;
                                }
                            } else {
                                if (SearchStringConvertLowerCase === SourcesConvertLowerCase.substr(currentPosition, SearchStringLength)) {
                                    FinalReturnValue++;
                                }
                            }
                        }
                    }
                }
                break;
            case 1:
                FinalReturnValue = [];
                if (SearchDirection === 0) {
                    for (; currentPosition < convertSourcesString.length; currentPosition++) {
                        if (currentPosition >= (convertSourcesString.length - SearchStringLength)) {
                            break;
                        }
                        strict1();
                    }
                } else {
                    currentPosition = convertSourcesString.length - SearchStringLength;
                    for (; currentPosition > 0; currentPosition--) {
                        if (currentPosition < SearchStringLength) {
                            break;
                        } else if (currentPosition === SearchStringLength) {
                            if (EnableStrict) {
                                if (convertNeedSearchString === convertSourcesString.substr(0, SearchStringLength)) {
                                    FinalReturnValue[FinalReturnValue.length] = convertSourcesString.substr(currentPosition, SearchStringLength);
                                }
                            } else {
                                if (SearchStringConvertLowerCase === SourcesConvertLowerCase.substr(0, SearchStringLength)) {
                                    FinalReturnValue[FinalReturnValue.length] = SourcesConvertLowerCase.substr(currentPosition, SearchStringLength);
                                }
                            }
                            break;
                        } else {
                            strict1();
                        }
                    }
                }
                break;
            default:
                throw new Error("ReturnValueType形参只能支持0或1值！");
        }
        return FinalReturnValue;
    }
}

/**
 * 文件搜索工具
 * ```
 * @param keyword 搜索的关键字
 * @param strictMode 使用严格模式
 * @param location_path 指定需要搜索的位置
 * @param search_depth 指定需要搜索的深度
 * */
function file_search_tools(keyword, strictMode, location_path, search_depth) {
    let final = [];
    let search_Depth_Pool = [];
    let ins_fs = require("fs");
    let ins_ps = require("path");

    if (typeof strictMode !== "boolean") {
        strictMode = false;
    }

    if (typeof search_depth !== "number" || !isFinite(search_depth) || isNaN(search_depth) || search_depth < 1) {
        search_depth = 1;
    }

    switch (typeof keyword) {
        case "string":
            if (String(keyword).length <= 0) {
                throw new Error("Keyword cannot be empty");
            }
            break;
        case "number":
            if (!isFinite(keyword) || isNaN(keyword)) {
                throw new Error("Keyword exception");
            }
            break;
        default:
            throw new Error("Keywords can only be text or numbers");
    }

    switch (Object.prototype.toString.call(location_path)) {
        case "[object Array]":
            break;
        case "[object String]":
            break;
        default:
            throw new Error("You must specify the desired search location");
    }

    function list_read(path_s) {
        return ins_fs.readdirSync(path_s);
    }

    function info_obj(paths) {
        let obj_info = {name: "", type: undefined, path: "", layout: 0};
        let stat_info = ins_fs.statSync(paths);
        if (stat_info.isFile()) {
            obj_info.type = "file";
        }
        if (stat_info.isDirectory()) {
            obj_info.type = "dirs";
        }
        let al = String(paths).split(ins_ps.sep);
        obj_info.layout = al.length - 1;
        obj_info.name = al[al.length - 1];
        obj_info.path = paths;
        return obj_info;
    }

    function pr(p_a) {
        let tmp_info;
        if (strictMode) {
            if (String(p_a).indexOf(keyword) > -1) {
                tmp_info = info_obj(p_a);
            }
        } else {
            if (String(p_a).toLowerCase().indexOf(keyword) > -1) {
                tmp_info = info_obj(p_a);
            }
        }
        return tmp_info;
    }

    function pr_1(path) {
        let tmp_list;
        try {
            let s_1;
            if (ins_fs.statSync(path).isDirectory()) {
                tmp_list = list_read(path);
                tmp_list.forEach(function (v2, i2, a2) {
                    try {
                        s_1 = info_obj(ins_ps.join(path, v2));
                        if (Object.prototype.toString.call(search_Depth_Pool[s_1.layout]) !== "[object Array]") {
                            search_Depth_Pool[s_1.layout] = [];
                        }
                        search_Depth_Pool[s_1.layout].push(s_1);
                    } catch (e2) {

                    }
                });
            } else {
                s_1 = info_obj(path);
                if (Object.prototype.toString.call(search_Depth_Pool[s_1.layout]) !== "[object Array]") {
                    search_Depth_Pool[s_1.layout] = [];
                }
                search_Depth_Pool[s_1.layout].push(s_1);
            }
        } catch (e1) {
        }
    }

    switch (Object.prototype.toString.call(location_path)) {
        case "[object Array]":
            location_path.forEach(function (v1, i1, a1) {
                pr_1(v1);
            });
            break;
        case "[object String]":
            pr_1(location_path);
            break
    }

    let start_1 = 1;

    while (true) {
        if (search_depth === start_1) {
            break;
        }
        search_Depth_Pool[start_1].forEach(function (v3, i3, a3) {
            pr_1(v3.path);
        })
        start_1++;
    }

    search_Depth_Pool.shift();
    start_1 = 0;
    while (true) {
        if (start_1 === search_Depth_Pool.length) {
            break;
        }
        search_Depth_Pool[start_1].forEach(function (v3) {
            let p = pr(v3.path);
            if (p) {
                final.push(p);
            }
        });
        start_1++;
    }
    search_Depth_Pool.splice(0);
    return final;
}

module.exports = {findString, findStringEx, findMultiEqualString, file_search_tools};